static void gtk_menu_deactivate (GtkMenuShell *menu_shell);
static void gtk_menu_position (GtkMenu *menu);
+static void gtk_menu_add (GtkContainer *menu,
+ GtkWidget *widget);
static void gtk_menu_remove (GtkContainer *menu,
GtkWidget *widget);
gtk_widget_queue_resize (GTK_WIDGET (menu));
}
+static GList *
+gtk_menu_get_items (GtkMenuShell *menu_shell)
+{
+ GtkMenuPrivate *priv = GTK_MENU (menu_shell)->priv;
+
+ return gtk_container_get_children (GTK_CONTAINER (priv->box));
+}
+
static void
gtk_menu_class_init (GtkMenuClass *class)
{
widget_class->grab_notify = gtk_menu_grab_notify;
widget_class->measure = gtk_menu_measure;
+ container_class->add = gtk_menu_add;
container_class->remove = gtk_menu_remove;
menu_shell_class->submenu_placement = GTK_LEFT_RIGHT;
menu_shell_class->insert = gtk_menu_real_insert;
menu_shell_class->get_popup_delay = gtk_menu_get_popup_delay;
menu_shell_class->move_current = gtk_menu_move_current;
+ menu_shell_class->get_items = gtk_menu_get_items;
/**
* GtkMenu::popped-up:
g_object_unref (menu);
}
+static void
+gtk_menu_add (GtkContainer *container,
+ GtkWidget *widget)
+{
+ GtkMenu *menu = GTK_MENU (container);
+ GtkMenuPrivate *priv = menu->priv;
+
+ gtk_container_add (GTK_CONTAINER (priv->box), widget);
+
+ menu_queue_resize (menu);
+}
+
static void
gtk_menu_remove (GtkContainer *container,
GtkWidget *widget)
#include "gtksizerequest.h"
#include "gtkwindow.h"
#include "gtkcontainerprivate.h"
+#include "gtkcheckmenuitem.h"
#include "gtkintl.h"
#include "gtkprivate.h"
#include "gtktypebuiltins.h"
#include "gtkwidgetprivate.h"
+#include "gtkbox.h"
#define MENU_BAR_POPUP_DELAY 0
struct _GtkMenuBar
{
GtkMenuShell menu_shell;
+
+ int toggle_size;
+ GtkWidget *box;
};
struct _GtkMenuBarClass
GtkMenuShellClass parent_class;
};
+static void gtk_menu_bar_add (GtkContainer *container,
+ GtkWidget *widget);
+static void gtk_menu_bar_remove (GtkContainer *container,
+ GtkWidget *widget);
+
static void gtk_menu_bar_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
static gint gtk_menu_bar_get_popup_delay (GtkMenuShell *menu_shell);
static void gtk_menu_bar_move_current (GtkMenuShell *menu_shell,
GtkMenuDirectionType direction);
+static void gtk_menu_bar_insert (GtkMenuShell *menu_shell,
+ GtkWidget *child,
+ gint position);
G_DEFINE_TYPE (GtkMenuBar, gtk_menu_bar, GTK_TYPE_MENU_SHELL)
+static GList *
+gtk_menu_bar_get_items (GtkMenuShell *menu_shell)
+{
+ GtkMenuBar *menu_bar = GTK_MENU_BAR (menu_shell);
+
+ return gtk_container_get_children (GTK_CONTAINER (menu_bar->box));
+}
+
static void
gtk_menu_bar_class_init (GtkMenuBarClass *class)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+ GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
GtkMenuShellClass *menu_shell_class = GTK_MENU_SHELL_CLASS (class);
GtkBindingSet *binding_set;
widget_class->root = gtk_menu_bar_root;
widget_class->unroot = gtk_menu_bar_unroot;
+ container_class->add = gtk_menu_bar_add;
+ container_class->remove = gtk_menu_bar_remove;
+
+ menu_shell_class->insert = gtk_menu_bar_insert;
menu_shell_class->submenu_placement = GTK_TOP_BOTTOM;
menu_shell_class->get_popup_delay = gtk_menu_bar_get_popup_delay;
menu_shell_class->move_current = gtk_menu_bar_move_current;
+ menu_shell_class->get_items = gtk_menu_bar_get_items;
binding_set = gtk_binding_set_by_class (class);
gtk_binding_entry_add_signal (binding_set,
static void
gtk_menu_bar_init (GtkMenuBar *menu_bar)
{
+ menu_bar->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_widget_set_parent (menu_bar->box, GTK_WIDGET (menu_bar));
}
/**
int *minimum_baseline,
int *natural_baseline)
{
- GtkMenuShell *menu_shell;
- GtkWidget *child;
- GList *children;
- gboolean use_toggle_size, use_maximize;
- gint child_minimum, child_natural;
-
- *minimum = 0;
- *natural = 0;
-
- menu_shell = GTK_MENU_SHELL (widget);
-
- children = menu_shell->priv->children;
-
- use_toggle_size = (orientation == GTK_ORIENTATION_HORIZONTAL);
- use_maximize = (orientation == GTK_ORIENTATION_VERTICAL);
+ GtkMenuBar *menu_bar = GTK_MENU_BAR (widget);
- while (children)
- {
- child = children->data;
- children = children->next;
-
- if (gtk_widget_get_visible (child))
- {
- gtk_widget_measure (child,
- orientation,
- for_size,
- &child_minimum, &child_natural,
- NULL, NULL);
-
- if (use_toggle_size)
- {
- gint toggle_size;
-
- gtk_menu_item_toggle_size_request (GTK_MENU_ITEM (child),
- &toggle_size);
-
- child_minimum += toggle_size;
- child_natural += toggle_size;
- }
-
- if (use_maximize)
- {
- *minimum = MAX (*minimum, child_minimum);
- *natural = MAX (*natural, child_natural);
- }
- else
- {
- *minimum += child_minimum;
- *natural += child_natural;
- }
- }
- }
+ gtk_widget_measure (menu_bar->box,
+ orientation,
+ for_size,
+ minimum, natural,
+ minimum_baseline, natural_baseline);
}
static void
int height,
int baseline)
{
- GtkMenuShell *menu_shell;
- GtkWidget *child;
- GList *children;
- GtkAllocation remaining_space;
- GArray *requested_sizes;
- gint toggle_size;
- guint i;
- int size;
- gboolean ltr = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR);
-
- menu_shell = GTK_MENU_SHELL (widget);
-
- if (!menu_shell->priv->children)
- return;
-
- remaining_space = (GtkAllocation) {0, 0, width, height};
- requested_sizes = g_array_new (FALSE, FALSE, sizeof (GtkRequestedSize));
- size = remaining_space.width;
-
- for (children = menu_shell->priv->children; children; children = children->next)
- {
- GtkRequestedSize request;
- child = children->data;
-
- if (!gtk_widget_get_visible (child))
- continue;
-
- request.data = child;
- gtk_widget_measure (child, GTK_ORIENTATION_HORIZONTAL,
- remaining_space.height,
- &request.minimum_size, &request.natural_size,
- NULL, NULL);
- gtk_menu_item_toggle_size_request (GTK_MENU_ITEM (child),
- &toggle_size);
- request.minimum_size += toggle_size;
- request.natural_size += toggle_size;
-
- gtk_menu_item_toggle_size_allocate (GTK_MENU_ITEM (child), toggle_size);
-
- g_array_append_val (requested_sizes, request);
-
- size -= request.minimum_size;
- }
+ GtkMenuBar *menu_bar = GTK_MENU_BAR (widget);
- size = gtk_distribute_natural_allocation (size,
- requested_sizes->len,
- (GtkRequestedSize *) requested_sizes->data);
-
- for (i = 0; i < requested_sizes->len; i++)
- {
- GtkAllocation child_allocation = remaining_space;
- GtkRequestedSize *request = &g_array_index (requested_sizes, GtkRequestedSize, i);
-
- child_allocation.width = request->minimum_size;
- remaining_space.width -= request->minimum_size;
-
- if (i + 1 == requested_sizes->len && GTK_IS_MENU_ITEM (request->data) &&
- GTK_MENU_ITEM (request->data)->priv->right_justify)
- ltr = !ltr;
-
- if (ltr)
- remaining_space.x += request->minimum_size;
- else
- child_allocation.x += remaining_space.width;
-
- gtk_widget_size_allocate (request->data, &child_allocation, -1);
- }
-
- g_array_free (requested_sizes, TRUE);
+ gtk_widget_size_allocate (menu_bar->box,
+ &(GtkAllocation) { 0, 0, width, height },
+ baseline);
}
static GList *
return menubar;
}
+
+static void
+gtk_menu_bar_add (GtkContainer *container,
+ GtkWidget *widget)
+{
+ GtkMenuBar *menu_bar = GTK_MENU_BAR (container);
+
+ gtk_container_add (GTK_CONTAINER (menu_bar->box), widget);
+}
+
+static void
+gtk_menu_bar_remove (GtkContainer *container,
+ GtkWidget *widget)
+{
+ GtkMenuBar *menu_bar = GTK_MENU_BAR (container);
+
+ gtk_container_remove (GTK_CONTAINER (menu_bar->box), widget);
+}
+
+static void
+gtk_menu_bar_insert (GtkMenuShell *menu_shell,
+ GtkWidget *child,
+ gint position)
+{
+ GtkMenuBar *menu_bar = GTK_MENU_BAR (menu_shell);
+
+ gtk_container_add (GTK_CONTAINER (menu_bar->box), child);
+}
GtkMenuShellPrivate *priv = menu_shell->priv;
GtkWidget *menu_item;
GdkEvent *event;
+ GtkWidget *item_shell;
event = gtk_get_current_event ();
menu_item = gtk_get_event_target_with_type (event, GTK_TYPE_MENU_ITEM);
+ if (menu_item)
+ item_shell = gtk_widget_get_ancestor (GTK_WIDGET (menu_item), GTK_TYPE_MENU_SHELL);
if (menu_item &&
_gtk_menu_item_is_selectable (menu_item) &&
- gtk_widget_get_parent (menu_item) == GTK_WIDGET (menu_shell))
+ item_shell == GTK_WIDGET (menu_shell))
{
if (menu_item != menu_shell->priv->active_menu_item)
{
if (menu_item)
{
if (_gtk_menu_item_is_selectable (menu_item) &&
- gtk_widget_get_parent (menu_item) == GTK_WIDGET (menu_shell) &&
+ item_shell == GTK_WIDGET (menu_shell) &&
menu_item != priv->active_menu_item)
{
priv->active = TRUE;
g_object_unref (menu_item);
}
+static GList *
+gtk_menu_shell_get_items (GtkMenuShell *menu_shell)
+{
+ return GTK_MENU_SHELL_GET_CLASS (menu_shell)->get_items (menu_shell);
+}
+
/* Distance should be +/- 1 */
static gboolean
gtk_menu_shell_real_move_selected (GtkMenuShell *menu_shell,
if (priv->active_menu_item)
{
- GList *node = g_list_find (priv->children, priv->active_menu_item);
+ GList *children = gtk_menu_shell_get_items (menu_shell);
+ GList *node = g_list_find (children, priv->active_menu_item);
GList *start_node = node;
if (distance > 0)
if (node)
node = node->next;
else
- node = priv->children;
+ node = children;
}
}
else
if (node)
node = node->prev;
else
- node = g_list_last (priv->children);
+ node = g_list_last (children);
}
}
if (node)
gtk_menu_shell_select_item (menu_shell, node->data);
+
+ g_list_free (children);
}
return TRUE;
gtk_menu_shell_select_first (GtkMenuShell *menu_shell,
gboolean search_sensitive)
{
- GtkMenuShellPrivate *priv;
+ GList *children;
GList *tmp_list;
g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell));
- priv = menu_shell->priv;
-
- tmp_list = priv->children;
+ children = gtk_menu_shell_get_items (menu_shell);
+ tmp_list = children;
while (tmp_list)
{
GtkWidget *child = tmp_list->data;
_gtk_menu_item_is_selectable (child))
{
gtk_menu_shell_select_item (menu_shell, child);
- return;
+ break;
}
tmp_list = tmp_list->next;
}
+
+ g_list_free (children);
}
void
_gtk_menu_shell_select_last (GtkMenuShell *menu_shell,
gboolean search_sensitive)
{
- GtkMenuShellPrivate *priv = menu_shell->priv;
GList *tmp_list;
+ GList *children;
- tmp_list = g_list_last (priv->children);
+ children = gtk_menu_shell_get_items (menu_shell);
+ tmp_list = g_list_last (children);
while (tmp_list)
{
GtkWidget *child = tmp_list->data;
_gtk_menu_item_is_selectable (child))
{
gtk_menu_shell_select_item (menu_shell, child);
- return;
+ break;
}
tmp_list = tmp_list->prev;
}
+
+ g_list_free (children);
}
static gboolean
gpointer user_data)
{
GtkMenuShell *menu_shell = user_data;
+ GList *children;
GtkWidget *child;
- child = g_list_nth_data (menu_shell->priv->children, position);
+ children = gtk_menu_shell_get_items (menu_shell);
+
+ child = g_list_nth_data (children, position);
/* We use destroy here because in the case of an item with a submenu,
* the attached-to from the submenu holds a ref on the item and a
* simple gtk_container_remove() isn't good enough to break that.
*/
gtk_widget_destroy (child);
+
+ g_list_free (children);
}
static void
gboolean with_separators)
{
GtkActionMuxer *muxer;
+ GList *children, *l;
g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell));
g_return_if_fail (model == NULL || G_IS_MENU_MODEL (model));
g_clear_pointer (&menu_shell->priv->tracker, gtk_menu_tracker_free);
- while (menu_shell->priv->children)
- gtk_container_remove (GTK_CONTAINER (menu_shell), menu_shell->priv->children->data);
+ children = gtk_menu_shell_get_items (menu_shell);
+ for (l = children; l; l = l->next)
+ gtk_widget_destroy (GTK_WIDGET (l->data));
+ g_list_free (children);
if (model)
menu_shell->priv->tracker = gtk_menu_tracker_new (GTK_ACTION_OBSERVABLE (muxer), model,